package genetic.q1.functions;

import genetic.q1.functions.sumlist.statements.End;

import java.util.Stack;

public class Program {
	
	Statement[] code;
	Statement[] extraEnds;
	int programCounter;
	int maxBlocks;
	Variable returnVar;
	
	public Program(Statement[] code, Variable returnVar, int maxBlocks){
		this.code = code;
		this.returnVar = returnVar;
		this.maxBlocks = maxBlocks;
		Analize();
	}
	
	public void Analize(){
		Stack<Integer> tmpStack = new Stack<Integer>();
		for (int i=0; i<code.length; i++){
			if (code[i].isBeginStatement()){
				tmpStack.push(i);
			}
			if (code[i].isEndStatement() && !tmpStack.isEmpty()){
				int backTrackPlace = tmpStack.pop();
				code[i].setParam(backTrackPlace);
				code[backTrackPlace].setParam(i+1);
			}
		}
		extraEnds = new Statement[tmpStack.size()];
		int index = 0;
		while (!tmpStack.isEmpty()){
			extraEnds[index] = new End();
			int backTrackPlace = tmpStack.pop();
			extraEnds[index].setParam(backTrackPlace);
			code[backTrackPlace].setParam(code.length+index+1);
			index++;
		}
	}
	
	private void reset() {
		for (Statement st: code){
			st.reset();
		}
	}

	
	public int execute(/*SumlistPhenotype phen*/){
		reset();
		int blockCounter = 0;
		for (programCounter = 0; programCounter<code.length+extraEnds.length && blockCounter < maxBlocks; blockCounter++){
//			System.out.println(" - " + programCounter + " - ");
//			phen.printAllVars();
//			System.out.println();
			if (programCounter<code.length){
				programCounter = code[programCounter].execute(this);
			} else {
				programCounter = extraEnds[programCounter-code.length].execute(this);
				
			}
		}
		if (programCounter==code.length+extraEnds.length){
//			System.out.println("Woohoo!");
			return returnVar.getValue();
		} else return 0;
		
	}

	public int getCounter() {
		return programCounter;
	}
	
	
	public String toString(){
		String acc = "";
		for (int i = 0; i < code.length; i++) {
			acc += i+". " + code[i].toString() + "\n";
		}
		
		for (int i = 0; i < extraEnds.length; i++) {
			acc += (i+code.length)+". " + extraEnds[i].toString() + "\n";
		}
		return acc;
	}
}
